package com.cq.hd.common.utils;

import com.cq.hd.common.annotation.Required;
import com.cq.hd.common.response.Throw;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;

/**
 * @description: 数据交互
 * @author: mYunYu
 * @date: 2021/7/7 16:02
 * @version: v1.0
 */
public class BeanUtils extends org.springframework.beans.BeanUtils{

    private static final Logger logger = LoggerFactory.getLogger(BeanUtils.class);

    private static ObjectMapper mapper = new ObjectMapper();

    static {
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    }

    public static <T> T json2Object(String json, Class<T> c) {
        try {
            return mapper.readValue(json, c);
        } catch (IOException e) {
            logger.error("json 转换 {} 异常", c.getName(), e);
        }
        return null;
    }

    public static String object2Json(Object o) {
        try {
            return mapper.writeValueAsString(o);
        } catch (JsonProcessingException e) {
            logger.error("object:[{}] 转换 string 异常", o, e);
        }
        return null;
    }

    public static void checkRequiredFields(Object bean, String... ignore) {
        List<String> requiredFields = new ArrayList<>();
        List<Field> fields = new ArrayList<>();
        Class<?> cls = bean.getClass();
        while (cls != null) {
            fields.addAll(Arrays.asList(cls.getDeclaredFields()));
            cls = cls.getSuperclass();
        }

        for (Field field : fields) {
            try {
                boolean isAccessible = field.isAccessible();
                field.setAccessible(true);
                if (field.isAnnotationPresent(Required.class) && (field.get(bean) == null || field.get(bean) instanceof String && StringUtils.isNullOrEmpty(field.get(bean).toString()))) {
                    if (ignore == null || Arrays.binarySearch(ignore, field.getName()) < 0) {
                        requiredFields.add(field.getName());
                    }
                }

                field.setAccessible(isAccessible);
            } catch (IllegalArgumentException | IllegalAccessException | SecurityException var6) {
                var6.printStackTrace();
            }
        }

        if (!requiredFields.isEmpty()) {
            String msg = "必填字段 " + requiredFields + " 必须提供值";
            logger.debug(msg);
            Throw.isBusinessException(msg);
        }
    }

    /**
     * @Description: 集合数据的拷贝
     * @Param: [sources: 数据源类 target: 目标类::new(eg: UserVO::new)]
     * @Return: java.util.List<T>
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:05
     */
    public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target) {
        return copyListProperties(sources, target, null);
    }

    /**
     * @Description: 带回调函数的集合数据的拷贝（可自定义字段拷贝规则）
     * @Param: [sources: 数据源类 target: 目标类::new(eg: UserVO::new) callBack: 回调函数]
     * @Return: java.util.List<T>
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:06
     */
    public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target, BeanCopyUtilCallBack<S, T> callBack) {
        if(sources == null){
            return new ArrayList<>();
        }

        List<T> list = new ArrayList<>(sources.size());
        for (S source : sources) {
            T t = target.get();
            copyProperties(source, t);
            list.add(t);
            if (callBack != null) {
                // 回调
                callBack.callBack(source, t);
            }
        }
        return list;
    }

}
